use std::fs;
use std::path::PathBuf;

use axum::Json;
use serde_json::{json, Value};

use crate::{code, file::{self, remove::remove_file_rel, utils::exist_rel}, query, utils::host::{upload_host, upload_url}};

pub async fn move_file(temp:&str, folder:&str) -> Result<Option<String>, Json<Value>> {
    let folder = if folder.is_empty() { "fs" } else { folder };
    if !temp.contains("/temp/"){
        return Ok(Some(temp.to_owned()));
    };
    let folder = if folder.is_empty() { "fs" } else { folder };

    let temp_str;
    if temp.contains("http") {
        let host = upload_host();
        let path = temp.strip_prefix(&host).unwrap_or_default();
        temp_str = path.to_owned()
    }else{
        temp_str = temp.to_owned()
    }
    
    // 判断文件是否存在
    let folder_path = "upload/".to_owned() + folder;
    let _ = file::create::create_dir_all_rel(&folder_path).await?;
    // 目标文件
    let arr = temp_str.rsplit("/").collect::<Vec<&str>>();
    
    let file_path =  folder_path + "/" + arr[0]; 
    let save_path = folder.to_owned() + "/" + arr[0];
    
    // 文件存在不移动
    if exist_rel(&file_path)? {
        return Ok( Some( save_path ) )
    }
    // 被移动文件
    let temap_path = PathBuf::from("./".to_owned() + &temp_str);
    
    let folder_path = PathBuf::from( "./".to_owned() + &file_path );
    // 移动文件
    let rename = fs::rename(temap_path, folder_path);
    match rename {
        Ok(_f) => Ok( Some(save_path) ),
        Err(e) => Err( code::sys_("上传正式图片错误：".to_owned() + &e.to_string()) )
    }
}
// 单图上传
pub async fn upload(body:&Value, field:&str, folder:&str) -> Result<String, Json<Value>>{
    let rs = get_upload_url(&query::str(body, field)?,folder).await;
    delete_file(body, field).await?;
    rs
}
pub async fn upload_op(body:&Value, field:&str, folder:&str) -> Result<Option<String>, Json<Value>>{
    let url = query::str_op(body, field)?;
    match url {
        Some(f) => {
            let rs = get_upload_url(&f,folder).await?;
            delete_file(body, field).await?;
            Ok( Some( rs ) )
        },
        None => {
            delete_file(body, field).await?;
            Ok(None)
        }
    }
}
pub async fn get_upload_url(url:&str, folder:&str) -> Result<String, Json<Value>>{
    if url.contains("/temp/") {
        let url = move_file( &url, folder ).await?;
        Ok(url.unwrap_or_default())
    }else {
        let host = upload_url();
        let rs = if url.contains(&host) { url.strip_prefix(&host).unwrap_or_default() } else { url };
        Ok(rs.to_owned())
    }
}
pub async fn delete_file(body:&Value, field:&str) -> Result<(), Json<Value>> {
    if let Some(url) = query::str_op(body, &format!("{}_old", field))?{
        let url = if url.contains("upload") { url.strip_prefix( &upload_url() ).unwrap_or_default() } else { &url };
        remove_file_rel(&format!("upload/{}", url)).await.unwrap_or_default();
    }
    Ok(())
}
// 多文件移动
pub async fn uploads(body:&Value, field:&str, folder:&str) -> Result<Value, Json<Value>>{
    let rs = get_uploads_url(query::json(body, field)?, folder).await;
    delete_files(body,field).await?;
    rs
}
pub async fn uploads_op(body:&Value, field:&str, folder:&str) -> Result<Option<Value>, Json<Value>>{
    let url = query::json_op(body, field)?;
    match url {
        Some(f) => {
            let rs = get_uploads_url(f, folder).await?;
            delete_files(body,field).await?;
            Ok(Some(rs))
        },
        None => {
            delete_files(body,field).await?;
            Ok(None)
        }
    }
}
// 处理数组中的旧文件与新文件
pub async fn get_uploads_url(url:Value, folder:&str) -> Result<Value, Json<Value>>{
    let arr = url.as_array();
    match arr {
        Some(p) => {
            let mut vec: Vec<String> = Vec::new();
            for v in p{
                if let Some( rs ) = v.as_str() {
                    if rs.contains("/temp/") {
                        let url = move_file( rs, folder ).await?;
                        vec.push(url.unwrap_or_default());
                    }else {
                        let host = upload_url();
                        let rs = if rs.contains(&host) { rs.strip_prefix(&host).unwrap_or_default() } else { rs };
                        vec.push(rs.to_owned());
                    }
                }
            }
            
            Ok( json!(vec) )
        },
        None => Ok(json!([]))
    }
}
pub async fn delete_files(body:&Value, field:&str) -> Result<(), Json<Value>> {
    if let Some(f) = query::json_op(body, &format!("{}_old", field))?{
        if let Some(old) = f.as_array(){
            for v in old {
                if let Some(url) = v.as_str() {
                    let url = if url.contains("upload") { url.strip_prefix( &upload_url() ).unwrap_or_default() } else { &url };
                    remove_file_rel(&format!("upload/{}", url)).await.unwrap_or_default();
                }
            }
        }
    }
    Ok(())
}